home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / g_phys.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  21.8 KB  |  960 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // g_phys.c
  21.  
  22. #include "g_local.h"
  23.  
  24. /*
  25.  
  26.  
  27. pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
  28.  
  29. onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
  30.  
  31. doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
  32. bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
  33. corpses are SOLID_NOT and MOVETYPE_TOSS
  34. crates are SOLID_BBOX and MOVETYPE_TOSS
  35. walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
  36. flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
  37.  
  38. solid_edge items only clip against bsp models.
  39.  
  40. */
  41.  
  42.  
  43. /*
  44. ============
  45. SV_TestEntityPosition
  46.  
  47. ============
  48. */
  49. edict_t    *SV_TestEntityPosition (edict_t *ent)
  50. {
  51.     trace_t    trace;
  52.     int        mask;
  53.  
  54.     
  55.     if (ent->clipmask)
  56.         mask = ent->clipmask;
  57.     else
  58.         mask = MASK_SOLID;
  59.     trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask);
  60.  
  61.     if (trace.startsolid)
  62.         return g_edicts;
  63.         
  64.     return NULL;
  65. }
  66.  
  67.  
  68. /*
  69. ================
  70. SV_CheckVelocity
  71. ================
  72. */
  73. void SV_CheckVelocity (edict_t *ent)
  74. {
  75.     int        i;
  76.  
  77. //
  78. // bound velocity
  79. //
  80.     for (i=0 ; i<3 ; i++)
  81.     {
  82.         if (ent->velocity[i] > sv_maxvelocity->value)
  83.             ent->velocity[i] = sv_maxvelocity->value;
  84.         else if (ent->velocity[i] < -sv_maxvelocity->value)
  85.             ent->velocity[i] = -sv_maxvelocity->value;
  86.     }
  87. }
  88.  
  89. /*
  90. =============
  91. SV_RunThink
  92.  
  93. Runs thinking code for this frame if necessary
  94. =============
  95. */
  96. qboolean SV_RunThink (edict_t *ent)
  97. {
  98.     float    thinktime;
  99.  
  100.     thinktime = ent->nextthink;
  101.     if (thinktime <= 0)
  102.         return true;
  103.     if (thinktime > level.time+0.001)
  104.         return true;
  105.     
  106.     ent->nextthink = 0;
  107.     if (!ent->think)
  108.         gi.error ("NULL ent->think");
  109.     ent->think (ent);
  110.  
  111.     return false;
  112. }
  113.  
  114. /*
  115. ==================
  116. SV_Impact
  117.  
  118. Two entities have touched, so run their touch functions
  119. ==================
  120. */
  121. void SV_Impact (edict_t *e1, trace_t *trace)
  122. {
  123.     edict_t        *e2;
  124. //    cplane_t    backplane;
  125.  
  126.     e2 = trace->ent;
  127.  
  128.     if (e1->touch && e1->solid != SOLID_NOT)
  129.         e1->touch (e1, e2, &trace->plane, trace->surface);
  130.     
  131.     if (e2->touch && e2->solid != SOLID_NOT)
  132.         e2->touch (e2, e1, NULL, NULL);
  133. }
  134.  
  135.  
  136. /*
  137. ==================
  138. ClipVelocity
  139.  
  140. Slide off of the impacting object
  141. returns the blocked flags (1 = floor, 2 = step / wall)
  142. ==================
  143. */
  144. #define    STOP_EPSILON    0.1
  145.  
  146. int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
  147. {
  148.     float    backoff;
  149.     float    change;
  150.     int        i, blocked;
  151.     
  152.     blocked = 0;
  153.     if (normal[2] > 0)
  154.         blocked |= 1;        // floor
  155.     if (!normal[2])
  156.         blocked |= 2;        // step
  157.     
  158.     backoff = DotProduct (in, normal) * overbounce;
  159.  
  160.     for (i=0 ; i<3 ; i++)
  161.     {
  162.         change = normal[i]*backoff;
  163.         out[i] = in[i] - change;
  164.         if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
  165.             out[i] = 0;
  166.     }
  167.     
  168.     return blocked;
  169. }
  170.  
  171.  
  172. /*
  173. ============
  174. SV_FlyMove
  175.  
  176. The basic solid body movement clip that slides along multiple planes
  177. Returns the clipflags if the velocity was modified (hit something solid)
  178. 1 = floor
  179. 2 = wall / step
  180. 4 = dead stop
  181. ============
  182. */
  183. #define    MAX_CLIP_PLANES    5
  184. int SV_FlyMove (edict_t *ent, float time, int mask)
  185. {
  186.     edict_t        *hit;
  187.     int            bumpcount, numbumps;
  188.     vec3_t        dir;
  189.     float        d;
  190.     int            numplanes;
  191.     vec3_t        planes[MAX_CLIP_PLANES];
  192.     vec3_t        primal_velocity, original_velocity, new_velocity;
  193.     int            i, j;
  194.     trace_t        trace;
  195.     vec3_t        end;
  196.     float        time_left;
  197.     int            blocked;
  198.     
  199.     numbumps = 4;
  200.     
  201.     blocked = 0;
  202.     VectorCopy (ent->velocity, original_velocity);
  203.     VectorCopy (ent->velocity, primal_velocity);
  204.     numplanes = 0;
  205.     
  206.     time_left = time;
  207.  
  208.     ent->groundentity = NULL;
  209.     for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
  210.     {
  211.         for (i=0 ; i<3 ; i++)
  212.             end[i] = ent->s.origin[i] + time_left * ent->velocity[i];
  213.  
  214.         trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);
  215.  
  216.         if (trace.allsolid)
  217.         {    // entity is trapped in another solid
  218.             VectorCopy (vec3_origin, ent->velocity);
  219.             return 3;
  220.         }
  221.  
  222.         if (trace.fraction > 0)
  223.         {    // actually covered some distance
  224.             VectorCopy (trace.endpos, ent->s.origin);
  225.             VectorCopy (ent->velocity, original_velocity);
  226.             numplanes = 0;
  227.         }
  228.  
  229.         if (trace.fraction == 1)
  230.              break;        // moved the entire distance
  231.  
  232.         hit = trace.ent;
  233.  
  234.         if (trace.plane.normal[2] > 0.7)
  235.         {
  236.             blocked |= 1;        // floor
  237.             if ( hit->solid == SOLID_BSP)
  238.             {
  239.                 ent->groundentity = hit;
  240.                 ent->groundentity_linkcount = hit->linkcount;
  241.             }
  242.         }
  243.         if (!trace.plane.normal[2])
  244.         {
  245.             blocked |= 2;        // step
  246.         }
  247.  
  248. //
  249. // run the impact function
  250. //
  251.         SV_Impact (ent, &trace);
  252.         if (!ent->inuse)
  253.             break;        // removed by the impact function
  254.  
  255.         
  256.         time_left -= time_left * trace.fraction;
  257.         
  258.     // cliped to another plane
  259.         if (numplanes >= MAX_CLIP_PLANES)
  260.         {    // this shouldn't really happen
  261.             VectorCopy (vec3_origin, ent->velocity);
  262.             return 3;
  263.         }
  264.  
  265.         VectorCopy (trace.plane.normal, planes[numplanes]);
  266.         numplanes++;
  267.  
  268. //
  269. // modify original_velocity so it parallels all of the clip planes
  270. //
  271.         for (i=0 ; i<numplanes ; i++)
  272.         {
  273.             ClipVelocity (original_velocity, planes[i], new_velocity, 1);
  274.             for (j=0 ; j<numplanes ; j++)
  275.                 if (j != i)
  276.                 {
  277.                     if (DotProduct (new_velocity, planes[j]) < 0)
  278.                         break;    // not ok
  279.                 }
  280.             if (j == numplanes)
  281.                 break;
  282.         }
  283.         
  284.         if (i != numplanes)
  285.         {    // go along this plane
  286.             VectorCopy (new_velocity, ent->velocity);
  287.         }
  288.         else
  289.         {    // go along the crease
  290.             if (numplanes != 2)
  291.             {
  292. //                gi.dprintf ("clip velocity, numplanes == %i\n",numplanes);
  293.                 VectorCopy (vec3_origin, ent->velocity);
  294.                 return 7;
  295.             }
  296.             CrossProduct (planes[0], planes[1], dir);
  297.             d = DotProduct (dir, ent->velocity);
  298.             VectorScale (dir, d, ent->velocity);
  299.         }
  300.  
  301. //
  302. // if original velocity is against the original velocity, stop dead
  303. // to avoid tiny occilations in sloping corners
  304. //
  305.         if (DotProduct (ent->velocity, primal_velocity) <= 0)
  306.         {
  307.             VectorCopy (vec3_origin, ent->velocity);
  308.             return blocked;
  309.         }
  310.     }
  311.  
  312.     return blocked;
  313. }
  314.  
  315.  
  316. /*
  317. ============
  318. SV_AddGravity
  319.  
  320. ============
  321. */
  322. void SV_AddGravity (edict_t *ent)
  323. {
  324.     ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME;
  325. }
  326.  
  327. /*
  328. ===============================================================================
  329.  
  330. PUSHMOVE
  331.  
  332. ===============================================================================
  333. */
  334.  
  335. /*
  336. ============
  337. SV_PushEntity
  338.  
  339. Does not change the entities velocity at all
  340. ============
  341. */
  342. trace_t SV_PushEntity (edict_t *ent, vec3_t push)
  343. {
  344.     trace_t    trace;
  345.     vec3_t    start;
  346.     vec3_t    end;
  347.     int        mask;
  348.  
  349.     VectorCopy (ent->s.origin, start);
  350.     VectorAdd (start, push, end);
  351.  
  352. retry:
  353.     if (ent->clipmask)
  354.         mask = ent->clipmask;
  355.     else
  356.         mask = MASK_SOLID;
  357.  
  358.     trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);
  359.     
  360.     VectorCopy (trace.endpos, ent->s.origin);
  361.     gi.linkentity (ent);
  362.  
  363.     if (trace.fraction != 1.0)
  364.     {
  365.         SV_Impact (ent, &trace);
  366.  
  367.         // if the pushed entity went away and the pusher is still there
  368.         if (!trace.ent->inuse && ent->inuse)
  369.         {
  370.             // move the pusher back and try again
  371.             VectorCopy (start, ent->s.origin);
  372.             gi.linkentity (ent);
  373.             goto retry;
  374.         }
  375.     }
  376.  
  377.     if (ent->inuse)
  378.         G_TouchTriggers (ent);
  379.  
  380.     return trace;
  381. }                    
  382.  
  383.  
  384. typedef struct
  385. {
  386.     edict_t    *ent;
  387.     vec3_t    origin;
  388.     vec3_t    angles;
  389.     float    deltayaw;
  390. } pushed_t;
  391. pushed_t    pushed[MAX_EDICTS], *pushed_p;
  392.  
  393. edict_t    *obstacle;
  394.  
  395. /*
  396. ============
  397. SV_Push
  398.  
  399. Objects need to be moved back on a failed push,
  400. otherwise riders would continue to slide.
  401. ============
  402. */
  403. qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove)
  404. {
  405.     int            i, e;
  406.     edict_t        *check, *block;
  407.     vec3_t        mins, maxs;
  408.     pushed_t    *p;
  409.     vec3_t        org, org2, move2, forward, right, up;
  410.  
  411.     // clamp the move to 1/8 units, so the position will
  412.     // be accurate for client side prediction
  413.     for (i=0 ; i<3 ; i++)
  414.     {
  415.         float    temp;
  416.         temp = move[i]*8.0;
  417.         if (temp > 0.0)
  418.             temp += 0.5;
  419.         else
  420.             temp -= 0.5;
  421.         move[i] = 0.125 * (int)temp;
  422.     }
  423.  
  424.     // find the bounding box
  425.     for (i=0 ; i<3 ; i++)
  426.     {
  427.         mins[i] = pusher->absmin[i] + move[i];
  428.         maxs[i] = pusher->absmax[i] + move[i];
  429.     }
  430.  
  431. // we need this for pushing things later
  432.     VectorSubtract (vec3_origin, amove, org);
  433.     AngleVectors (org, forward, right, up);
  434.  
  435. // save the pusher's original position
  436.     pushed_p->ent = pusher;
  437.     VectorCopy (pusher->s.origin, pushed_p->origin);
  438.     VectorCopy (pusher->s.angles, pushed_p->angles);
  439.     if (pusher->client)
  440.         pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW];
  441.     pushed_p++;
  442.  
  443. // move the pusher to it's final position
  444.     VectorAdd (pusher->s.origin, move, pusher->s.origin);
  445.     VectorAdd (pusher->s.angles, amove, pusher->s.angles);
  446.     gi.linkentity (pusher);
  447.  
  448. // see if any solid entities are inside the final position
  449.     check = g_edicts+1;
  450.     for (e = 1; e < globals.num_edicts; e++, check++)
  451.     {
  452.         if (!check->inuse)
  453.             continue;
  454.         if (check->movetype == MOVETYPE_PUSH
  455.         || check->movetype == MOVETYPE_STOP
  456.         || check->movetype == MOVETYPE_NONE
  457.         || check->movetype == MOVETYPE_NOCLIP)
  458.             continue;
  459.  
  460.         if (!check->area.prev)
  461.             continue;        // not linked in anywhere
  462.  
  463.     // if the entity is standing on the pusher, it will definitely be moved
  464.         if (check->groundentity != pusher)
  465.         {
  466.             // see if the ent needs to be tested
  467.             if ( check->absmin[0] >= maxs[0]
  468.             || check->absmin[1] >= maxs[1]
  469.             || check->absmin[2] >= maxs[2]
  470.             || check->absmax[0] <= mins[0]
  471.             || check->absmax[1] <= mins[1]
  472.             || check->absmax[2] <= mins[2] )
  473.                 continue;
  474.  
  475.             // see if the ent's bbox is inside the pusher's final position
  476.             if (!SV_TestEntityPosition (check))
  477.                 continue;
  478.         }
  479.  
  480.         if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher))
  481.         {
  482.             // move this entity
  483.             pushed_p->ent = check;
  484.             VectorCopy (check->s.origin, pushed_p->origin);
  485.             VectorCopy (check->s.angles, pushed_p->angles);
  486.             pushed_p++;
  487.  
  488.             // try moving the contacted entity 
  489.             VectorAdd (check->s.origin, move, check->s.origin);
  490.             if (check->client)
  491.             {    // FIXME: doesn't rotate monsters?
  492.                 check->client->ps.pmove.delta_angles[YAW] += amove[YAW];
  493.             }
  494.  
  495.             // figure movement due to the pusher's amove
  496.             VectorSubtract (check->s.origin, pusher->s.origin, org);
  497.             org2[0] = DotProduct (org, forward);
  498.             org2[1] = -DotProduct (org, right);
  499.             org2[2] = DotProduct (org, up);
  500.             VectorSubtract (org2, org, move2);
  501.             VectorAdd (check->s.origin, move2, check->s.origin);
  502.  
  503.             // may have pushed them off an edge
  504.             if (check->groundentity != pusher)
  505.                 check->groundentity = NULL;
  506.  
  507.             block = SV_TestEntityPosition (check);
  508.             if (!block)
  509.             {    // pushed ok
  510.                 gi.linkentity (check);
  511.                 // impact?
  512.                 continue;
  513.             }
  514.  
  515.             // if it is ok to leave in the old position, do it
  516.             // this is only relevent for riding entities, not pushed
  517.             // FIXME: this doesn't acount for rotation
  518.             VectorSubtract (check->s.origin, move, check->s.origin);
  519.             block = SV_TestEntityPosition (check);
  520.             if (!block)
  521.             {
  522.                 pushed_p--;
  523.                 continue;
  524.             }
  525.         }
  526.         
  527.         // save off the obstacle so we can call the block function
  528.         obstacle = check;
  529.  
  530.         // move back any entities we already moved
  531.         // go backwards, so if the same entity was pushed
  532.         // twice, it goes back to the original position
  533.         for (p=pushed_p-1 ; p>=pushed ; p--)
  534.         {
  535.             VectorCopy (p->origin, p->ent->s.origin);
  536.             VectorCopy (p->angles, p->ent->s.angles);
  537.             if (p->ent->client)
  538.             {
  539.                 p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw;
  540.             }
  541.             gi.linkentity (p->ent);
  542.         }
  543.         return false;
  544.     }
  545.  
  546. //FIXME: is there a better way to handle this?
  547.     // see if anything we moved has touched a trigger
  548.     for (p=pushed_p-1 ; p>=pushed ; p--)
  549.         G_TouchTriggers (p->ent);
  550.  
  551.     return true;
  552. }
  553.  
  554. /*
  555. ================
  556. SV_Physics_Pusher
  557.  
  558. Bmodel objects don't interact with each other, but
  559. push all box objects
  560. ================
  561. */
  562. void SV_Physics_Pusher (edict_t *ent)
  563. {
  564.     vec3_t        move, amove;
  565.     edict_t        *part, *mv;
  566.  
  567.     // if not a team captain, so movement will be handled elsewhere
  568.     if ( ent->flags & FL_TEAMSLAVE)
  569.         return;
  570.  
  571.     // make sure all team slaves can move before commiting
  572.     // any moves or calling any think functions
  573.     // if the move is blocked, all moved objects will be backed out
  574. //retry:
  575.     pushed_p = pushed;
  576.     for (part = ent ; part ; part=part->teamchain)
  577.     {
  578.         if (part->velocity[0] || part->velocity[1] || part->velocity[2] ||
  579.             part->avelocity[0] || part->avelocity[1] || part->avelocity[2]
  580.             )
  581.         {    // object is moving
  582.             VectorScale (part->velocity, FRAMETIME, move);
  583.             VectorScale (part->avelocity, FRAMETIME, amove);
  584.  
  585.             if (!SV_Push (part, move, amove))
  586.                 break;    // move was blocked
  587.         }
  588.     }
  589.     if (pushed_p > &pushed[MAX_EDICTS])
  590.         gi.error (ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted");
  591.  
  592.     if (part)
  593.     {
  594.         // the move failed, bump all nextthink times and back out moves
  595.         for (mv = ent ; mv ; mv=mv->teamchain)
  596.         {
  597.             if (mv->nextthink > 0)
  598.                 mv->nextthink += FRAMETIME;
  599.         }
  600.  
  601.         // if the pusher has a "blocked" function, call it
  602.         // otherwise, just stay in place until the obstacle is gone
  603.         if (part->blocked)
  604.             part->blocked (part, obstacle);
  605. #if 0
  606.         // if the pushed entity went away and the pusher is still there
  607.         if (!obstacle->inuse && part->inuse)
  608.             goto retry;
  609. #endif
  610.     }
  611.     else
  612.     {
  613.         // the move succeeded, so call all think functions
  614.         for (part = ent ; part ; part=part->teamchain)
  615.         {
  616.             SV_RunThink (part);
  617.         }
  618.     }
  619. }
  620.  
  621. //==================================================================
  622.  
  623. /*
  624. =============
  625. SV_Physics_None
  626.  
  627. Non moving objects can only think
  628. =============
  629. */
  630. void SV_Physics_None (edict_t *ent)
  631. {
  632. // regular thinking
  633.     SV_RunThink (ent);
  634. }
  635.  
  636. /*
  637. =============
  638. SV_Physics_Noclip
  639.  
  640. A moving object that doesn't obey physics
  641. =============
  642. */
  643. void SV_Physics_Noclip (edict_t *ent)
  644. {
  645. // regular thinking
  646.     if (!SV_RunThink (ent))
  647.         return;
  648.     
  649.     VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
  650.     VectorMA (ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin);
  651.  
  652.     gi.linkentity (ent);
  653. }
  654.  
  655. /*
  656. ==============================================================================
  657.  
  658. TOSS / BOUNCE
  659.  
  660. ==============================================================================
  661. */
  662.  
  663. /*
  664. =============
  665. SV_Physics_Toss
  666.  
  667. Toss, bounce, and fly movement.  When onground, do nothing.
  668. =============
  669. */
  670. void SV_Physics_Toss (edict_t *ent)
  671. {
  672.     trace_t        trace;
  673.     vec3_t        move;
  674.     float        backoff;
  675.     edict_t        *slave;
  676.     qboolean    wasinwater;
  677.     qboolean    isinwater;
  678.     vec3_t        old_origin;
  679.  
  680. // regular thinking
  681.     SV_RunThink (ent);
  682.  
  683.     // if not a team captain, so movement will be handled elsewhere
  684.     if ( ent->flags & FL_TEAMSLAVE)
  685.         return;
  686.  
  687.     if (ent->velocity[2] > 0)
  688.         ent->groundentity = NULL;
  689.  
  690. // check for the groundentity going away
  691.     if (ent->groundentity)
  692.         if (!ent->groundentity->inuse)
  693.             ent->groundentity = NULL;
  694.  
  695. // if onground, return without moving
  696.     if ( ent->groundentity )
  697.         return;
  698.  
  699.     VectorCopy (ent->s.origin, old_origin);
  700.  
  701.     SV_CheckVelocity (ent);
  702.  
  703. // add gravity
  704.     if (ent->movetype != MOVETYPE_FLY
  705.     && ent->movetype != MOVETYPE_FLYMISSILE)
  706.         SV_AddGravity (ent);
  707.  
  708. // move angles
  709.     VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
  710.  
  711. // move origin
  712.     VectorScale (ent->velocity, FRAMETIME, move);
  713.     trace = SV_PushEntity (ent, move);
  714.     if (!ent->inuse)
  715.         return;
  716.  
  717.     if (trace.fraction < 1)
  718.     {
  719.         if (ent->movetype == MOVETYPE_BOUNCE)
  720.             backoff = 1.5;
  721.         else
  722.             backoff = 1;
  723.  
  724.         ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff);
  725.  
  726.     // stop if on ground
  727.         if (trace.plane.normal[2] > 0.7)
  728.         {        
  729.             if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE )
  730.             {
  731.                 ent->groundentity = trace.ent;
  732.                 ent->groundentity_linkcount = trace.ent->linkcount;
  733.                 VectorCopy (vec3_origin, ent->velocity);
  734.                 VectorCopy (vec3_origin, ent->avelocity);
  735.             }
  736.         }
  737.  
  738. //        if (ent->touch)
  739. //            ent->touch (ent, trace.ent, &trace.plane, trace.surface);
  740.     }
  741.     
  742. // check for water transition
  743.     wasinwater = (ent->watertype & MASK_WATER);
  744.     ent->watertype = gi.pointcontents (ent->s.origin);
  745.     isinwater = ent->watertype & MASK_WATER;
  746.  
  747.     if (isinwater)
  748.         ent->waterlevel = 1;
  749.     else
  750.         ent->waterlevel = 0;
  751.  
  752.     if (!wasinwater && isinwater)
  753.         gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
  754.     else if (wasinwater && !isinwater)
  755.         gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
  756.  
  757. // move teamslaves
  758.     for (slave = ent->teamchain; slave; slave = slave->teamchain)
  759.     {
  760.         VectorCopy (ent->s.origin, slave->s.origin);
  761.         gi.linkentity (slave);
  762.     }
  763. }
  764.  
  765. /*
  766. ===============================================================================
  767.  
  768. STEPPING MOVEMENT
  769.  
  770. ===============================================================================
  771. */
  772.  
  773. /*
  774. =============
  775. SV_Physics_Step
  776.  
  777. Monsters freefall when they don't have a ground entity, otherwise
  778. all movement is done with discrete steps.
  779.  
  780. This is also used for objects that have become still on the ground, but
  781. will fall if the floor is pulled out from under them.
  782. FIXME: is this true?
  783. =============
  784. */
  785.  
  786. //FIXME: hacked in for E3 demo
  787. #define    sv_stopspeed        100
  788. #define sv_friction            6
  789. #define sv_waterfriction    1
  790.  
  791. void SV_AddRotationalFriction (edict_t *ent)
  792. {
  793.     int        n;
  794.     float    adjustment;
  795.  
  796.     VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
  797.     adjustment = FRAMETIME * sv_stopspeed * sv_friction;
  798.     for (n = 0; n < 3; n++)
  799.     {
  800.         if (ent->avelocity[n] > 0)
  801.         {
  802.             ent->avelocity[n] -= adjustment;
  803.             if (ent->avelocity[n] < 0)
  804.                 ent->avelocity[n] = 0;
  805.         }
  806.         else
  807.         {
  808.             ent->avelocity[n] += adjustment;
  809.             if (ent->avelocity[n] > 0)
  810.                 ent->avelocity[n] = 0;
  811.         }
  812.     }
  813. }
  814.  
  815. void SV_Physics_Step (edict_t *ent)
  816. {
  817.     qboolean    wasonground;
  818.     qboolean    hitsound = false;
  819.     float        *vel;
  820.     float        speed, newspeed, control;
  821.     float        friction;
  822.     edict_t        *groundentity;
  823.     int            mask;
  824.  
  825.     // airborn monsters should always check for ground
  826.     if (!ent->groundentity)
  827.         M_CheckGround (ent);
  828.  
  829.     groundentity = ent->groundentity;
  830.  
  831.     SV_CheckVelocity (ent);
  832.  
  833.     if (groundentity)
  834.         wasonground = true;
  835.     else
  836.         wasonground = false;
  837.         
  838.     if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
  839.         SV_AddRotationalFriction (ent);
  840.  
  841.     // add gravity except:
  842.     //   flying monsters
  843.     //   swimming monsters who are in the water
  844.     if (! wasonground)
  845.         if (!(ent->flags & FL_FLY))
  846.             if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2)))
  847.             {
  848.                 if (ent->velocity[2] < sv_gravity->value*-0.1)
  849.                     hitsound = true;
  850.                 if (ent->waterlevel == 0)
  851.                     SV_AddGravity (ent);
  852.             }
  853.  
  854.     // friction for flying monsters that have been given vertical velocity
  855.     if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0))
  856.     {
  857.         speed = fabs(ent->velocity[2]);
  858.         control = speed < sv_stopspeed ? sv_stopspeed : speed;
  859.         friction = sv_friction/3;
  860.         newspeed = speed - (FRAMETIME * control * friction);
  861.         if (newspeed < 0)
  862.             newspeed = 0;
  863.         newspeed /= speed;
  864.         ent->velocity[2] *= newspeed;
  865.     }
  866.  
  867.     // friction for flying monsters that have been given vertical velocity
  868.     if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
  869.     {
  870.         speed = fabs(ent->velocity[2]);
  871.         control = speed < sv_stopspeed ? sv_stopspeed : speed;
  872.         newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
  873.         if (newspeed < 0)
  874.             newspeed = 0;
  875.         newspeed /= speed;
  876.         ent->velocity[2] *= newspeed;
  877.     }
  878.  
  879.     if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
  880.     {
  881.         // apply friction
  882.         // let dead monsters who aren't completely onground slide
  883.         if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY)))
  884.             if (!(ent->health <= 0.0 && !M_CheckBottom(ent)))
  885.             {
  886.                 vel = ent->velocity;
  887.                 speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
  888.                 if (speed)
  889.                 {
  890.                     friction = sv_friction;
  891.  
  892.                     control = speed < sv_stopspeed ? sv_stopspeed : speed;
  893.                     newspeed = speed - FRAMETIME*control*friction;
  894.  
  895.                     if (newspeed < 0)
  896.                         newspeed = 0;
  897.                     newspeed /= speed;
  898.  
  899.                     vel[0] *= newspeed;
  900.                     vel[1] *= newspeed;
  901.                 }
  902.             }
  903.  
  904.         if (ent->svflags & SVF_MONSTER)
  905.             mask = MASK_MONSTERSOLID;
  906.         else
  907.             mask = MASK_SOLID;
  908.         SV_FlyMove (ent, FRAMETIME, mask);
  909.  
  910.         gi.linkentity (ent);
  911.         G_TouchTriggers (ent);
  912.  
  913.         if (ent->groundentity)
  914.             if (!wasonground)
  915.                 if (hitsound)
  916.                     gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0);
  917.     }
  918.  
  919. // regular thinking
  920.     SV_RunThink (ent);
  921. }
  922.  
  923. //============================================================================
  924. /*
  925. ================
  926. G_RunEntity
  927.  
  928. ================
  929. */
  930. void G_RunEntity (edict_t *ent)
  931. {
  932.     if (ent->prethink)
  933.         ent->prethink (ent);
  934.  
  935.     switch ( (int)ent->movetype)
  936.     {
  937.     case MOVETYPE_PUSH:
  938.     case MOVETYPE_STOP:
  939.         SV_Physics_Pusher (ent);
  940.         break;
  941.     case MOVETYPE_NONE:
  942.         SV_Physics_None (ent);
  943.         break;
  944.     case MOVETYPE_NOCLIP:
  945.         SV_Physics_Noclip (ent);
  946.         break;
  947.     case MOVETYPE_STEP:
  948.         SV_Physics_Step (ent);
  949.         break;
  950.     case MOVETYPE_TOSS:
  951.     case MOVETYPE_BOUNCE:
  952.     case MOVETYPE_FLY:
  953.     case MOVETYPE_FLYMISSILE:
  954.         SV_Physics_Toss (ent);
  955.         break;
  956.     default:
  957.         gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype);            
  958.     }
  959. }
  960.